package cn.piflow.local

import java.util.concurrent.atomic.AtomicInteger

import cn.piflow.util.Logging
import org.quartz.{JobExecutionContext, Trigger, TriggerKey}

import scala.collection.mutable.ArrayBuffer

trait QuartzTrigger {
	def notifyFinalized(): Unit;

	def awaitFinalized(timeout: Long): Unit;

	def increaseFireCount(): Unit;

	def getFireCount(): Int;
}

trait QuartzTriggerTable {
	def getHistoricExecutions(): Seq[JobExecutionContext];

	def appendExecution(ctx: JobExecutionContext);

	def get(key: String): QuartzTrigger;

	def get(triggerKey: TriggerKey): QuartzTrigger = get(triggerKey.getName);

	def login(trigger: Trigger): Unit;
}

class QuartzTriggerImpl extends QuartzTrigger() {
	val termination = new Object();
	val counter = new AtomicInteger(0);

	def notifyFinalized() = {
		termination.synchronized {
			termination.notify();
		}
	}

	def awaitFinalized(timeout: Long) = {
		termination.synchronized {
			termination.wait(timeout);
		}
	}

	def increaseFireCount() = {
		counter.incrementAndGet();
	}

	def getFireCount() = counter.get;
}

class QuartzTriggerTableImpl(maxHistorySize: Int = 102400) extends QuartzTriggerTable with Logging {
	val triggers = collection.mutable.Map[String, QuartzTrigger]();
	val history = ArrayBuffer[JobExecutionContext]();
	val dirtyThreshold = 100;
	var dirtyFlag = 0;

	def get(key: String): QuartzTrigger = {
		triggers(key);
	}

	def getHistoricExecutions(): Seq[JobExecutionContext] = history;

	def appendExecution(ctx: JobExecutionContext) = {
		history += ctx;

		dirtyFlag += 1;
		if (dirtyFlag >= dirtyThreshold) {
			if (maxHistorySize >= 0 && history.size >= maxHistorySize)
				history.synchronized {
					history.trimStart(history.size - maxHistorySize);
				}

			dirtyFlag = 0;
		}
	}

	def login(trigger: Trigger) = {
		val name = trigger.getKey.getName;
		val te = new QuartzTriggerImpl();

		triggers.synchronized {
			triggers(name) = te;
		}

		logger.debug(s"registering ${trigger}");
	}
}